package com.simafei.flow.core.operator.impl;

import cn.hutool.core.text.CharPool;
import com.simafei.flow.core.common.CalcType;
import com.simafei.flow.core.common.Criterion;
import com.simafei.flow.core.common.ExpressionExecutor;
import com.simafei.flow.core.common.Operator;
import com.simafei.flow.core.exception.OperatorDefineException;
import com.simafei.flow.core.json.JsonUtils;
import com.simafei.flow.core.operator.OperatorHandler;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author fengpengju
 */
public class InOperatorHandler implements OperatorHandler {
    @Override
    public String handle(Criterion condition) {
        String right = condition.getRight();
        if (condition.getRightType() == CalcType.VARIABLE || condition.getRightType() == CalcType.EXPRESSION) {
            // 如果是变量，替换掉引号或者双引号
            right = right.replaceAll("\"", "");
            right = right.replaceAll("'", "");
        }
        return right + ".contains(" + condition.getLeft() + ")";
    }

    @Override
    public String sqlLeft(Criterion condition) {
        List<String> split = JsonUtils.parseArray(condition.getRight(), String.class);
        if (split.isEmpty()) {
            // 如果是IN一个空数组，报错
            throw new OperatorDefineException("IN操作符的右表达式不能为空数组");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < split.size(); i++) {
            sb.append("?");
            if (i != split.size() - 1) {
                sb.append(CharPool.COMMA);
            }
        }
        return condition.getLeft() + " " + condition.getOperator().getSqlOperator() + " (" + sb + ")";
    }

    @Override
    public List<String> sqlRight(Criterion condition, Map<String, Object> params) {
        List<String> sqlRights = JsonUtils.parseArray(condition.getRight(), String.class);
        if (condition.getRightType() == CalcType.CONSTANT) {
            return sqlRights;
        } else {
            return sqlRights.stream()
                    .map(right -> ExpressionExecutor.execute(right, params))
                    .map(o -> (String) o)
                    .collect(Collectors.toList());
        }
    }

    @Override
    public boolean support(Operator operator) {
        return Operator.IN == operator;
    }
}
